#include "cross_com.h"
#include <iostream>
#include <string.h>
#include <errno.h>

#include "media_server.h"
extern "C" 
{
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
}
#include "MultiCHData.h"

#ifdef _WIN32
#include <WS2tcpip.h>
// #pragma comment(lib,"libevent.lib")
// #pragma comment(lib,"libevent_core.lib")
// #pragma comment(lib,"libevent_extras.lib")

#else

#endif
using namespace std;

int g_server_port = 32005;


CMultiCHData * g_mulCh = CMultiCHData::getSingleton();

cross_thread_t  m_dataThdID = 0;
//accept
void do_accept_cb(evutil_socket_t listener, short evnet, void* arg);
//read
void read_cd(struct bufferevent*bev, void* arg);
//err
void error_cb(struct bufferevent*bev, short event, void* arg);
//write
void write_cd(struct bufferevent*bev,void* arg);

int server_proc(void *arg);

void do_accept_cb(evutil_socket_t listener, short evnet, void* arg)
{
//
	struct event_base* base = (struct event_base*)arg;
	//socket
	evutil_socket_t fd;
	//
	struct sockaddr_in sin;
	//
	socklen_t slen = sizeof(sin);
	fd = accept(listener, (struct sockaddr*)&sin, &slen);
	if (fd<0)
	{
        printf("error %d  accept fd %d ",errno,fd);
        return;
	}
	//int ch = g_multiPlayer.GetFreeCh();

//	CMultiPlayer::REPLAY_PROC * pPlayInfo = g_multiPlayer.GetProcInfo(ch);
	//
	struct bufferevent* bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
	//
	bufferevent_setcb(bev, read_cd, NULL, error_cb, NULL); //bufferevent_setcb(bev, read_cd, NULL, error_cb, pPlayInfo);
	//
	bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);

	//g_multiPlayer.UseCH(ch);
}

void read_cd(struct bufferevent*bev, void* arg)
{
	#define MAXPKT  64<<10
	//CMultiPlayer::REPLAY_PROC * pPlayInfo = (CMultiPlayer::REPLAY_PROC*) arg;
	int ch = 0;//pPlayInfo->ch;//(arg;
	int frm_size = 0;
	int ret = 0;
	char buf[MAXPKT] = {0};
	char * pRevBuf = buf;
	int total_sz = 0;

	int pkt_size = 0;
	int str_pos = 0;
	bool is_iFrm = false;
	int leaf_size = MAXPKT;

	while(true)
	{
	    pRevBuf = buf;
        frm_size = bufferevent_read(bev,pRevBuf, leaf_size);
        if(frm_size > 0)
        {
            total_sz += frm_size;
        }

        if(frm_size <= 0)
        {
            break;
        }
        pRevBuf+=frm_size;
        leaf_size -= MAXPKT - frm_size;
	}

	if(total_sz != 0)
	{
	    if(total_sz > 1024)
        {
		//  TRACE("Recive size %d .\n",total_sz);
        }
		g_mulCh->FIFO_WRITE_FRAME_MULCH((unsigned char *)buf,total_sz);

        int show_size = 512;

        if(total_sz < show_size)
        {
            show_size = total_sz;
        }

	//	ShowHexData(buf,32,32,true,"recive data");

	}


//	ret = g_multiPlayer.WriteData(ch,(unsigned char *)buf, total_sz);

}

void error_cb(struct bufferevent*bev, short event, void* arg)
{
//fd
//	CMultiPlayer::REPLAY_PROC * pPlayInfo = (CMultiPlayer::REPLAY_PROC*) arg;
	evutil_socket_t fd = bufferevent_getfd(bev);
	if (event&BEV_EVENT_TIMEOUT)
	{
		cout << "Timer out" << endl;
	}
	else if (event&BEV_EVENT_EOF)
	{
		//g_multiPlayer.FreeCH(pPlayInfo->ch);
		//
		cout << "connection closed" << endl;
	}
	else if (event&&BEV_EVENT_ERROR)
	{
		cout << "some other error" << endl;
	}
	bufferevent_free(bev);
}

void write_cd(struct bufferevent*bev, void* arg)
{
	char str[50] = {0};
	//fd
	evutil_socket_t fd = bufferevent_getfd(bev);
	cout << "please input something" << endl;
	//scanf_s("%s", &str);
	bufferevent_write(bev, &str, sizeof(str));
}

int EventMediaServerInit(int port)
{
	g_server_port = port;

	m_dataThdID= Cross_CreateThread((cross_start_routine)server_proc, NULL,NULL, SIZE_128KB);

	return 0;
}

int MediaServerDestroy(int port)
{

	return 0;
}

int server_proc(void *arg)
{
	int ret = 0;
	static bool bRun = false;

	if(bRun)
	{
		return -1;
	}
	bRun = true;
	evutil_socket_t listener;
#ifdef _WIN32
	WSADATA ws;
	if (WSAStartup(MAKEWORD(2,2),&ws)!=0)
	{
		bRun = false;
		return -1;
	}
#endif // _WIN32
	listener = socket(AF_INET, SOCK_STREAM, 0);
	evutil_make_listen_socket_reuseable(listener);
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = 0;
	sin.sin_port = htons(g_server_port);
	if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		perror("bind");
		bRun = false;
		return -1;
	}

	bRun = false;
	listen(listener, 10000);
	evutil_make_socket_nonblocking(listener);
	struct event_base* base = event_base_new();
	struct event*listen_event;
	listen_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept_cb, (void*)base);
	event_add(listen_event, NULL);
	event_base_dispatch(base);

	return ret;
}


